import time
import logging
from fastapi import FastAPI, HTTPException, Request, status, Depends
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
from typing import Optional
import asyncio
from app.model.qwen3_client import Qwen3Client

# 日志配置
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s %(levelname)s %(message)s',
    handlers=[logging.StreamHandler()]
)

app = FastAPI(
    title="MCP 服务 (流程图驱动)",
    description="基于流程图拆分的多模态/微服务编排 FastAPI 服务，集成大模型推理。",
    version="1.0.0"
)

# CORS 支持
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Pydantic 请求模型（参数校验）
class MCPRequest(BaseModel):
    request_id: str = Field(..., description="唯一请求ID")
    prompt: str = Field(..., min_length=1, max_length=2048, description="用户输入的自然语言指令")
    user: Optional[str] = Field(None, description="用户标识，可选")

class MCPResponse(BaseModel):
    request_id: str
    result: str
    duration_ms: int
    model: str

# 健康检查路由
def health():
    return {"status": "ok"}

app.add_api_route("/health", health, methods=["GET"], tags=["运维"])

# 依赖注入模型客户端
def get_qwen3_client():
    return Qwen3Client()

# 主流程路由（流程图：用户请求→参数校验→大模型推理→结果返回）
@app.post("/mcp/process", response_model=MCPResponse, tags=["主流程"])
async def mcp_process(
    req: MCPRequest,
    request: Request,
    qwen3_client: Qwen3Client = Depends(get_qwen3_client)
):
    logging.info(f"接收到请求：{req.request_id} from {request.client.host}")
    start = time.time()
    # 重试机制
    last_err = None
    for attempt in range(3):
        try:
            # 这里拆分流程图中的『大模型推理』步骤
            result = await asyncio.wait_for(
                qwen3_client.acall(req.prompt), timeout=5.0
            )
            duration = int((time.time() - start) * 1000)
            logging.info(f"模型调用耗时：{duration}ms | request_id={req.request_id}")
            return MCPResponse(
                request_id=req.request_id,
                result=result,
                duration_ms=duration,
                model=qwen3_client.model
            )
        except asyncio.TimeoutError:
            last_err = "模型推理超时"
            logging.error(f"模型推理超时 | request_id={req.request_id}")
        except ValueError as ve:
            logging.error(f"参数错误: {ve} | request_id={req.request_id}")
            raise HTTPException(status_code=400, detail=str(ve))
        except RuntimeError as re:
            if "不可用" in str(re):
                logging.error(f"模型服务不可用: {re} | request_id={req.request_id}")
                raise HTTPException(status_code=503, detail="模型服务不可用")
            last_err = str(re)
            logging.error(f"模型调用失败: {re} | request_id={req.request_id}")
        except Exception as e:
            last_err = str(e)
            logging.error(f"未知错误: {e} | request_id={req.request_id}")
        await asyncio.sleep(0.5)  # 重试间隔
    raise HTTPException(status_code=500, detail=f"模型调用失败: {last_err}")

# 全局异常处理
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
    logging.error(f"全局异常: {exc} | path={request.url.path}")
    return JSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content={"detail": str(exc)}
    ) 